package notify.xgx.com.notifydemo;

import android.app.Application;

import java.util.HashMap;

/**
 * Created by mik_eddy on 14/12/13
 */
public class MobileApplication extends Application {
    /**
     *全局回调池,有任何内部通知回调都在注册后添加到此hashmap中
     *
     */
    private static HashMap<String,NotifyInfo> appNotifyCallBackPool;


    /**
     * 获取全局回调池
     * @return
     */
    private static HashMap<String,NotifyInfo> getNotifyPool(){
        if(appNotifyCallBackPool==null)appNotifyCallBackPool=new HashMap<String, NotifyInfo>();
        return appNotifyCallBackPool;
    }

    /**
     * 私有保护的,请勿随便改为public
     * 从全局回调池中根据类名获取某一个回调对象(如果没有则会返回null)
     * @param key 需要传入的类名
     * @return
     */
    private static NotifyInfo getNotifyInfoFromPool(String key){
        NotifyInfo notifyinfo=getNotifyPool().get(key);
        //如果没有就返回null,请勿在null的时候再实例化,然后添加到pool中,否则,在某些错误的调用的时候就会在pool中生成垃圾
        //很有可能这些垃圾无法有效的回收
        return notifyinfo;
    }


    /**
     * 在某一个回调对象中添加回调监听,需要注意:
     * 1.一个回调对象只能有一个回调监听,重复添加则会覆盖掉原先的
     * 2.必须设置了回调监听后此回调才会起作用
     * 3.如果回调不使用了请调用removeNotifyCallBackFromPool方法从回调池删除(非常重要)
     * @param cls  需要传入的类
     * @param notifycallback 需要设置的回调监听
     */
    public static void addNotifyCallBackIntoPool(Class<?> cls,INotifycallBack notifycallback){
        String key=getClassName(cls);
        NotifyInfo notifyinfo=getNotifyInfoFromPool(key);
        if(notifyinfo==null)notifyinfo=new NotifyInfo();
        getNotifyPool().put(key,notifyinfo);
        getNotifyInfoFromPool(key).setNotifyCallBackListener(notifycallback);
    }


    /**
     * 在某一个回调对象中添加回调code,需要注意
     *1.回调code必须要在设置了回调监听后才有效(使用addNotifyCallBackIntoPool方法来添加回调监听)
     *2.
     * @param cls  需要传入的类
     * @param notifycode 需要添加的回调code
     */
    public static void addNotifynotifycode(Class<?> cls,NotifyInfo.NOTIFYCODE notifycode){
        String key=getClassName(cls);
        NotifyInfo notifyinfo=getNotifyInfoFromPool(key);
        if(notifyinfo==null)notifyinfo=new NotifyInfo();
        getNotifyPool().put(key,notifyinfo);
        getNotifyInfoFromPool(key).addNotifyCode(notifycode);
    }


    /**
     * 从全局回调池中删除某一个回调,请注意:
     * 1.如果页面或者某个类不使用了,必须要使用此方法注销掉回调!!!(请一定要执行)
     * 2.如果页面或类还在使用,但是却使用了此方法则会造成回调失效
     * @param cls 需要传入的类
     */
    public static void removeNotifyCallBackFromPool(Class<?> cls){
        String key=getClassName(cls);
        NotifyInfo notifyinfo=getNotifyInfoFromPool(key);
        if(notifyinfo!=null){
            notifyinfo.clear();
            PalLog.printE("remove notifycallback from pool key is:   "+key);
            getNotifyPool().remove(key);
            //remove之后会打印所有的存在于pool中的notify key,防止有没有remove的
            printAllNotifyKey();
        }
    }

    /**
     * 针对某一个单独类特定的回调(单点指定回调)
     * @param cls
     * @param notifycode
     * @return 返回对应注册的回调返回值
     */
    public static Object notifyCallBack(Class<?> cls,NotifyInfo.NOTIFYCODE notifycode,Object...objs){
        String key=getClassName(cls);
        NotifyInfo notifyinfo=getNotifyInfoFromPool(key);
        if(notifyinfo!=null){
            PalLog.printE("aaa","call notifycallback[method] key is:|"+key+"|     notifycode is:|"+notifycode+"|");
            return notifyinfo.notifyCallBack(notifycode,objs);
        }
        return null;
    }

    /**
     * 不针对某一个类,只要有此notifycode就回调(批量回调)
     * @param notifycode 需要批量回调的notifycode
     * @return 返回对应注册的回调返回值
     */
    public static Object notifyCallBack(NotifyInfo.NOTIFYCODE notifycode,Object...objs){
        Object[] keymaps=getNotifyPool().keySet().toArray();
        int length=keymaps.length;
        for (int i = 0; i < length; i++) {
            Object key=keymaps[i];
            NotifyInfo notifyinfo=getNotifyPool().get(key);
            if(notifyinfo!=null){
                PalLog.printE("aaa","call notifycallback key is:|"+key+"|     notifycode is:|"+notifycode+"|");
                notifyinfo.notifyCallBack(notifycode,objs);
            }
        }
        return null;
    }


    /**
     * 针对某一个单独类特定的,有延时的回调(单点指定,延时,回调)
     * @param cls   需要指定的类
     * @param notifycode 需要通知的notifycode
     * @param delay     延迟的毫秒数
     * @param respCallBack  到达延时指定的时间后会将回调结果通知到此callback中
     * @param objs  需要传入的参数
     */
    public static void notifyCallBackDelay(Class<?> cls,final NotifyInfo.NOTIFYCODE notifycode,int delay, final INotifycallBackResp respCallBack,final Object...objs){
        String key=getClassName(cls);
        NotifyInfo notifyinfo=getNotifyInfoFromPool(key);
        if(notifyinfo!=null){
            PalLog.printE("aaa","call notifyCallBackDelay key is:|"+key+"|  delaytime is:|"+delay+"|   notifycode is:|"+notifycode+"|");
            notifyinfo.notifyCallBackDelay(notifycode,delay,respCallBack,objs);
        }
    }


    /**
     * 打印所有的回调通知key(只有在测试的时候才会开启,以便更容易发现遗漏的,没有remove的回调对象)
     */
    private static void printAllNotifyKey(){
        if(PalLog.DEBUG){
            Object[] keys=getNotifyPool().keySet().toArray();
            if(keys!=null){
                int length=keys.length;
                PalLog.printE("==================printNotifyKey in pool start================");
                for (int i = 0; i < length; i++) {
                    PalLog.printE("key:|"+keys[i]+"|    is in pool index is:|"+i+"|");
                }
                PalLog.printE("==================printNotifyKey in pool end==================");
            }
        }
    }
    //****************************************************************************

    /**
     * 获取类名
     *
     * @param cls
     *            传入的class
     * @return
     */
    public static String getClassName(Class<?> cls) {
        String name = cls.getName();
        int indexDoller = name.indexOf("$");
        if (indexDoller != -1)
            return name.substring(0, indexDoller);
        return name;
    }

}
